package mgodb

import (
	"jgt-oper/src/model"
	"jgt-oper/src/schema"
	"jgt-oper/src/service/mongo"
	"jgt-oper/src/util"

	"github.com/facebookgo/inject"
	"github.com/globalsign/mgo"
	"github.com/globalsign/mgo/bson"
	"github.com/pkg/errors"
)

// 用户管理表名
const cUser = "oper_user"

// 用户常用功能项
const cUserCommonFunction = "oper_common_function"

// 登录历史
const cLoginHistory = "oper_login_history"

// 用户设置
const cUserSetting = "oper_user_setting"

// User 用户管理
type User struct {
	DB *mongo.DB
}

// Init 初始化
func (a *User) Init(g *inject.Graph, db *mongo.DB) {
	a.DB = db

	// 初始化mongo索引
	db.C(cUser, func(c *mgo.Collection) error {
		c.EnsureIndexKey("deleted")
		c.EnsureIndexKey("record_id", "deleted")
		c.EnsureIndex(mgo.Index{
			Key:    []string{"record_id"},
			Unique: true,
		})
		return nil
	})

	db.C(cLoginHistory, func(c *mgo.Collection) error {
		c.EnsureIndexKey("user_id")
		return nil
	})

	var val model.IUser = a
	g.Provide(&inject.Object{Value: val, Name: "IUser"})
}

// QueryPage 查询分页数据
func (a *User) QueryPage(params schema.UserQueryParam, pageIndex, pageSize uint) (int64, []*schema.User, error) {
	query := bson.M{}

	if v := params.Status; v > 0 {
		if v == 1 {
			query["deleted"] = 0
		}
		if v == 2 {
			query["deleted"] = bson.M{"$not": bson.M{"$lte": 0}}

		}
	}

	if v := params.Nickname; v != "" {
		query["nickname"] = bson.M{"$regex": util.TranSearch(v)}
	}

	if v := params.RealName; v != "" {
		query["real_name"] = bson.M{"$regex": util.TranSearch(v)}
	}

	if v := params.EnterpriseID; v != "" {
		query["enterprise_id"] = v
	}

	if v := params.Gender; v > 0 {
		query["gender"] = v
	}

	if v := params.AuthStatus; v > 0 {
		query["auth_status"] = v
	}

	if v := params.UserType; v != "" {
		query["user_type"] = v
	}

	if v := params.From; v > 0 {
		if l := params.To; l > 0 {
			query["created"] = bson.M{"$gte": v, "$lte": l}
		} else {
			query["created"] = bson.M{"$gte": v}
		}

	}
	if v := params.To; v > 0 && query["created"] == nil {
		query["created"] = bson.M{"$lte": v}
	}

	var total int64
	var items []*schema.User
	err := a.DB.C(cUser, func(c *mgo.Collection) error {
		n, err := c.Find(query).Count()
		if err != nil {
			return err
		}
		total = int64(n)
		if total == 0 {
			return nil
		}

		return c.Find(query).Sort("-_id").Skip(int((pageIndex - 1) * pageSize)).Limit(int(pageSize)).All(&items)
	})
	if err != nil {
		return 0, nil, errors.Wrapf(err, "查询分页数据发生错误")
	}

	return total, items, nil
}

// Search 搜索数据
func (a *User) Search(search string, count int) ([]*schema.User, error) {
	query := bson.M{
		"deleted": 0,
	}
	query["$or"] = []bson.M{
		{"nickname": bson.M{"$regex": util.TranSearch(search)}},
		{"real_name": bson.M{"$regex": util.TranSearch(search)}},
	}

	var items []*schema.User
	err := a.DB.C(cUser, func(c *mgo.Collection) error {

		return c.Find(query).Sort("-_id").Limit(count).All(&items)
	})
	if err != nil {
		return nil, errors.Wrapf(err, "模糊查询数据发生错误")
	}

	return items, nil
}

// QuerySelect 查询选择数据
func (a *User) QuerySelect(params schema.UserQueryParam) ([]*schema.User, error) {
	return nil, nil
}

// Count 用户统计
func (a *User) Count(params schema.UserQueryParam) (int64, error) {
	query := bson.M{
		"deleted": 0,
	}

	if v := params.Nickname; v != "" {
		query["nickname"] = v
	}

	if v := params.RealName; v != "" {
		query["real_name"] = v
	}

	if v := params.EnterpriseID; v != "" {
		query["enterprise_id"] = v
	}

	if v := params.Gender; v > 0 {
		query["gender"] = v
	}

	if v := params.AuthStatus; v > 0 {
		query["auth_status"] = v
	}

	if v := params.From; v > 0 {
		if l := params.To; l > 0 {
			query["created"] = bson.M{"$gte": v, "$lte": l}
		} else {
			query["created"] = bson.M{"$gte": v}
		}

	}
	if v := params.To; v > 0 && query["created"] == nil {
		query["created"] = bson.M{"$lte": v}
	}

	var total int64
	err := a.DB.C(cUser, func(c *mgo.Collection) error {
		n, err := c.Find(query).Count()
		if err != nil {
			return err
		}
		total = int64(n)

		return nil

	})

	return total, err
}

// Create 创建用户
func (a *User) Create(item *schema.User) error {
	err := a.DB.C(cUser, func(c *mgo.Collection) error {
		id, err := a.DB.IncrID(cUser)
		if err != nil {
			return err
		}
		item.ID = id
		return c.Insert(item)
	})
	if err != nil {
		return errors.Wrapf(err, "创建数据发生错误")
	}

	return nil
}

// Update 更新用户信息
func (a *User) Update(recordID string, info map[string]interface{}) error {
	err := a.DB.C(cUser, func(c *mgo.Collection) error {
		return c.Update(bson.M{"record_id": recordID}, bson.M{"$set": info})
	})
	if err != nil {
		return errors.Wrapf(err, "更新数据发生错误")
	}
	return nil
}

// Get 获取用户信息
func (a *User) Get(recordID string) (*schema.User, error) {
	var user schema.User
	err := a.DB.C(cUser, func(c *mgo.Collection) error {
		return c.Find(bson.M{"record_id": recordID}).One(&user)
	})
	if err != nil {
		if err == mgo.ErrNotFound {
			return nil, nil
		}
		return nil, errors.Wrapf(err, "精确查询数据发生错误")
	}
	return &user, nil
}

// CheckNickname 检查用户昵称
func (a *User) CheckNickname(nickname string) (bool, error) {
	var exists bool
	err := a.DB.C(cUser, func(c *mgo.Collection) error {
		n, err := c.Find(bson.M{"deleted": 0, "nickname": nickname}).Count()
		if err != nil {
			return err
		}
		exists = n > 0
		return nil
	})
	if err != nil {
		return false, errors.Wrapf(err, "检查用户昵称发生错误")
	}

	return exists, nil
}

// QueryCommonFunction 查询常用功能
func (a *User) QueryCommonFunction(userID string) ([]string, error) {
	var item schema.UserCommonFunction
	err := a.DB.C(cUserCommonFunction, func(c *mgo.Collection) error {
		err := c.FindId(userID).One(&item)
		if err != nil {
			if err == mgo.ErrNotFound {
				return nil
			}
		}
		return err
	})
	if err != nil {
		return nil, errors.Wrapf(err, "查询常用功能发生错误")
	}
	return item.Functions, nil
}

// SaveCommonFunction 保存常用功能
func (a *User) SaveCommonFunction(userID string, items []string) error {
	err := a.DB.C(cUserCommonFunction, func(c *mgo.Collection) error {
		_, err := c.UpsertId(userID, bson.M{"$set": bson.M{"functions": items}})
		return err
	})
	if err != nil {
		return errors.Wrapf(err, "保存常用功能发生错误")
	}
	return nil
}

// CreateLoginHistory 创建登录历史
func (a *User) CreateLoginHistory(item *schema.LoginHistory) error {
	err := a.DB.C(cLoginHistory, func(c *mgo.Collection) error {
		id, err := a.DB.IncrID(cLoginHistory)
		if err != nil {
			return err
		}
		item.ID = id
		return c.Insert(item)
	})
	if err != nil {
		return errors.Wrapf(err, "创建数据发生错误")
	}

	return nil
}

// SaveSetting 保存用户设置
func (a *User) SaveSetting(setting *schema.UserSetting) error {
	err := a.DB.C(cUserSetting, func(c *mgo.Collection) error {
		_, err := c.UpsertId(setting.UserID, setting)
		return err
	})
	if err != nil {
		return errors.Wrapf(err, "保存用户设置发生错误")
	}
	return nil
}

// GetSetting 获取用户设置
func (a *User) GetSetting(userID string) (*schema.UserSetting, error) {
	var item schema.UserSetting
	err := a.DB.C(cUserSetting, func(c *mgo.Collection) error {
		err := c.FindId(userID).One(&item)
		if err != nil {
			if err == mgo.ErrNotFound {
				return nil
			}
		}
		return err
	})
	if err != nil {
		return nil, errors.Wrapf(err, "获取用户设置发生错误")
	}
	return &item, nil
}
